package com.kongchengji.spider.picServer;

import com.alibaba.fastjson.JSONObject;
import com.kongchengji.spider.station.domain.PicJsonDO;
import com.kongchengji.spider.station.domain.PictureDO;
import com.kongchengji.spider.util.HttpClientPool;
import com.kongchengji.spider.util.LaunchVPNUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class RequestPicServer implements CommandLineRunner {
    @Value("${vpn.disconnectCommand}")
    private String disConnectCommand;
    @Value("${vpn.connectCommand}")
    private String connectCommand;
    @Value("${picServer.getPicJsonUrl}")
    private String getPicJsonUrl;
    @Value("${picServer.savePicBase64Url}")
    private String savePicBase64Url;

    private static boolean isConnectVPN = false;
    private ExecutorService executors = Executors.newFixedThreadPool(20);

    /**
     * 请求采集后台,通过采集后台
     * @param args
     */
    @Override
    public void run(String... args) {
       Thread t1 =  new Thread(new Runnable() {
            @Override
            public void run() {
                //变量定义在死循环外部
                long startTime;
                long endTime;
                String body;
                HttpResponse response;
                PicJsonDO picJsonDO;
                HttpGet httpGet = new HttpGet(getPicJsonUrl);
                while (true) {
                    //1.不断请求服务器的接口，并判断是否有返回值；
                    //2.将得到的json数据转为picJsonDO对象
                    //3.拿到下载图片的相关参数下载图片
                    HttpClient client = HttpClientPool.getHttpClient();
                    try {
                        response = client.execute(httpGet);
                        body = EntityUtils.toString(response.getEntity());
                        if (StringUtils.isNotBlank(body)) {
                            //2.将得到的json数据转为picJsonDO对象
                            picJsonDO = JSONObject.parseObject(body, PicJsonDO.class);
                            //3.拿到下载图片的相关参数下载图片
                            List<Future> futureList = new ArrayList<>();
                            startTime = System.currentTimeMillis();
                            for (PictureDO pictureDO : picJsonDO.getPictureDOS()) {
                                futureList.add(executors.submit(new DownloadPic(pictureDO, picJsonDO.getRefer())));
                            }
                            for (Future future : futureList) {
                                future.get();
                            }
                            endTime = System.currentTimeMillis();
                            System.out.println(endTime -startTime);
                            ReturePicByteToServer.reterData(picJsonDO, savePicBase64Url);
                        }else {
                            //防止不存在数据时不间断访问接口
                            Thread.sleep(3000);
                        }
                    } catch(Exception e){
                        e.printStackTrace();
                    }
                }
            }
        });
        t1.start();
}

public class DownloadPic extends Thread {
    PictureDO pictureDO;
    String referValue;

    public DownloadPic(PictureDO pictureDO, String referValue) {
        this.pictureDO = pictureDO;
        this.referValue = referValue;
    }

    @Override
    public void run() {
        InputStream input = null;
        ByteArrayOutputStream output = null;
        HttpClient httpclient = HttpClientPool.getHttpClient();
        CloseableHttpResponse response = null;
        HttpGet httpget =null;
        try {
//            URL url = new URL(pictureDO.getPictureUrl());
//            URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(), url.getQuery(), null);
             httpget = new HttpGet(pictureDO.getPictureUrl());
            // 设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(50000).setConnectTimeout(50000).build();
            //设置请求头
            httpget.setHeader( "User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.79 Safari/537.1" );

            if (StringUtils.isNotBlank(referValue)) {
                httpget.setHeader("Referer", referValue);
            }
            httpget.setConfig(requestConfig);
            //防止连接超时或下载失败的情况
            for(int i = 0;i < 3;i++){
                try{
                    response = (CloseableHttpResponse) httpclient.execute(httpget);
                    break;
                }
                catch (IOException e){
                    e.printStackTrace();
                }
            }
            HttpEntity entity = response.getEntity();
            if (response.getStatusLine().getStatusCode() != 200) {
                //改变vpn连接标记
                if (!isConnectVPN) {
                    isConnectVPN = true;
                    LaunchVPNUtil launchVPNUtil = LaunchVPNUtil.getInstance();
                    launchVPNUtil.executeCmd(connectCommand);
                    //三分钟后自动断开
                    new Thread(new ReleaseVPN()).start();
                }
                Thread.currentThread().sleep(2000);
                response = (CloseableHttpResponse) httpclient.execute(httpget);
                entity = response.getEntity();
            }
            if (entity != null) {
                input = entity.getContent();
                output = new ByteArrayOutputStream();
                byte[] buff = new byte[1024];
                int len;
                while ((len = input.read(buff, 0, 1024)) != -1) {
                    output.write(buff, 0, len);
                }
                pictureDO.setPictureUrl(Base64.encodeBase64String(output.toByteArray()));
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(httpget != null){
                    httpget.releaseConnection();
                }
                if (response != null) {
                    response.close();
                }
                if (input != null) {
                    input.close();
                }
                if (output != null) {
                    output.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}



public class ReleaseVPN implements Runnable {

    @Override
    public void run() {
        try {
            Thread.currentThread().sleep(1000 * 60 * 3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LaunchVPNUtil launchVPNUtil = LaunchVPNUtil.getInstance();
        launchVPNUtil.executeCmd(disConnectCommand);
        isConnectVPN = false;
    }
}

}
